// 合约数据服务 - 直接从 CTP API 获取真实数据
import type { ContractInfo, ContractCategory } from '@/types/trading'
import { ctpService } from './ctpService'
import { ContractCache } from '@/utils/contractCache'
// import { autoReconnectService } from './autoReconnectService'

// 全局订阅管理器
class SubscriptionManager {
  private static instance: SubscriptionManager
  private subscriptions = new Map<string, Set<string>>() // contractCode -> Set<panelId>

  public static getInstance(): SubscriptionManager {
    if (!SubscriptionManager.instance) {
      SubscriptionManager.instance = new SubscriptionManager()
    }
    return SubscriptionManager.instance
  }

  // 添加订阅
  public addSubscription(contractCode: string, panelId: string): boolean {
    if (!this.subscriptions.has(contractCode)) {
      this.subscriptions.set(contractCode, new Set())
    }

    const panelSet = this.subscriptions.get(contractCode)!
    const wasEmpty = panelSet.size === 0
    panelSet.add(panelId)

    return wasEmpty // 返回是否是第一个订阅者
  }

  // 移除订阅
  public removeSubscription(contractCode: string, panelId: string): boolean {
    if (!this.subscriptions.has(contractCode)) {
      return true // 已经没有订阅了
    }

    const panelSet = this.subscriptions.get(contractCode)!
    panelSet.delete(panelId)

    const isEmpty = panelSet.size === 0
    if (isEmpty) {
      this.subscriptions.delete(contractCode)
    }

    return isEmpty // 返回是否是最后一个订阅者
  }

  // 检查是否有订阅
  public hasSubscription(contractCode: string): boolean {
    return this.subscriptions.has(contractCode) && this.subscriptions.get(contractCode)!.size > 0
  }

  // 获取订阅数量
  public getSubscriptionCount(contractCode: string): number {
    return this.subscriptions.get(contractCode)?.size || 0
  }
}

/**
 * 合约数据服务类
 * 负责管理和提供合约数据 - 直接从 CTP API 获取真实数据
 */
export class ContractService {
  private static instance: ContractService
  private contracts: ContractInfo[] = []
  private categories: ContractCategory[] = []
  private isInitialized: boolean = false
  private isLoading: boolean = false
  private lastDataSource: 'ctp' | 'cache' | 'unknown' = 'unknown' // 记录最后一次数据来源

  private constructor() {
    // 不在构造函数中初始化，改为异步初始化
  }

  public static getInstance(): ContractService {
    if (!ContractService.instance) {
      ContractService.instance = new ContractService()
    }
    return ContractService.instance
  }

  /**
   * 异步初始化合约数据 - 直接从 CTP API 获取
   */
  public async initialize(): Promise<void> {
    if (this.isInitialized || this.isLoading) {
      return
    }

    this.isLoading = true

    try {

      // 确保交易连接可用，如果没有则自动重连
      // const isConnected = await autoReconnectService.ensureTraderConnection()
      // if (!isConnected) {
      //   throw new Error('CTP 交易 API 未连接，请先登录')
      // }

      // 查询所有合约信息
      const result = await ctpService.queryInstruments()

      if (result.success && result.data) {
        this.processRealContractData(result.data)
        this.isInitialized = true
      } else {
        throw new Error(result.error || '查询合约信息失败')
      }
    } catch (error) {
      throw error
    } finally {
      this.isLoading = false
    }
  }

  /**
   * 处理从 CTP API 获取的合约数据
   */
  private processRealContractData(rawData: any[]): void {
    const contractMap = new Map<string, ContractInfo[]>()


    // 处理原始数据并转换为 ContractInfo 格式
    rawData.forEach(item => {
      // 只处理活跃的交易合约
      if (item.is_trading !== 1) {
        return
      }

      const contract: ContractInfo = {
        code: item.instrument_id || '',
        name: item.instrument_name || item.instrument_id || '',
        category: item.product_id || '', // 直接使用CTP返回的产品ID作为分类
        categoryCode: item.product_id || '',
        month: this.extractMonth(item.instrument_id),
        fullCode: item.instrument_id || '',
        isActive: item.is_trading === 1,
        lastPrice: 0, // 初始价格为0，后续通过行情数据更新
        changePercent: 0, // 需要通过行情数据计算
        volume: 0, // 初始成交量为0，后续通过行情数据更新
        openInterest: 0, // 初始持仓量为0，后续通过行情数据更新
        priceTick: item.price_tick || 0 // 价格间距
      }

      const categoryCode = contract.categoryCode.toUpperCase()
      if (!contractMap.has(categoryCode)) {
        contractMap.set(categoryCode, [])
      }
      contractMap.get(categoryCode)!.push(contract)
    })

    // 转换为分类格式
    this.contracts = []
    this.categories = []

    contractMap.forEach((contracts, categoryCode) => {
      // 按合约代码排序
      contracts.sort((a, b) => a.code.localeCompare(b.code))

      this.contracts.push(...contracts)

      // 直接使用CTP返回的产品ID作为分类名称
      this.categories.push({
        code: categoryCode,
        name: categoryCode, // 直接使用产品代码，不进行中文映射
        contracts: contracts
      })
    })

    // 按分类代码排序
    this.categories.sort((a, b) => a.code.localeCompare(b.code))


    // 打印前几个分类的信息
    this.categories.slice(0, 5).forEach(category => {
    })
  }

  /**
   * 从合约代码中提取月份信息
   */
  private extractMonth(instrumentId: string): string {
    if (!instrumentId) return ''

    // 提取数字部分，通常是年月格式，如 2501 表示 25年1月
    const match = instrumentId.match(/(\d{2})(\d{2})$/)
    if (match) {
      const month = parseInt(match[2])
      return `${month}月`
    }

    return ''
  }



  /**
   * 获取所有合约（异步版本，确保数据已初始化）
   */
  public async getAllContracts(): Promise<ContractInfo[]> {
    await this.initialize()
    return [...this.contracts]
  }

  /**
   * 获取所有分类（异步版本，确保数据已初始化）
   */
  public async getAllCategories(): Promise<ContractCategory[]> {
    if (!this.isInitialized) {
      await this.initializeWithTimeout()
    }
    return [...this.categories]
  }

  /**
   * 获取所有合约（同步版本，用于已初始化的情况）
   */
  public getAllContractsSync(): ContractInfo[] {
    return [...this.contracts]
  }

  /**
   * 获取所有分类（同步版本，用于已初始化的情况）
   */
  public getAllCategoriesSync(): ContractCategory[] {
    return [...this.categories]
  }

  /**
   * 根据关键词搜索合约（异步版本）
   */
  public async searchContracts(keyword: string): Promise<ContractInfo[]> {
    await this.initialize()

    if (!keyword.trim()) {
      return this.getAllContractsSync()
    }

    const lowerKeyword = keyword.toLowerCase().trim()

    return this.contracts.filter(contract =>
      contract.code.toLowerCase().includes(lowerKeyword) ||
      contract.name.toLowerCase().includes(lowerKeyword) ||
      contract.category.toLowerCase().includes(lowerKeyword) ||
      contract.categoryCode.toLowerCase().includes(lowerKeyword) ||
      contract.fullCode.toLowerCase().includes(lowerKeyword)
    )
  }

  /**
   * 根据合约代码获取合约信息（异步版本）
   */
  public async getContractByCode(code: string): Promise<ContractInfo | null> {
    await this.initialize()
    return this.contracts.find(contract =>
      contract.code === code || contract.fullCode === code
    ) || null
  }

  /**
   * 根据合约代码获取合约信息（不需要全量数据初始化）
   * 这个方法用于交易面板，只需要基本的合约信息用于行情订阅
   */
  public getContractInfoByCode(code: string): ContractInfo {
    // 为交易面板创建基本的合约信息，不需要查询全量合约数据
    return {
      code: code,
      name: code, // 使用代码作为名称
      category: this.extractCategoryFromCode(code),
      categoryCode: this.extractCategoryFromCode(code),
      month: this.extractMonth(code),
      fullCode: code,
      isActive: true, // 假设是活跃合约
      lastPrice: 0,
      changePercent: 0,
      volume: 0,
      openInterest: 0
    }
  }

  /**
   * 从合约代码中提取品种代码
   */
  private extractCategoryFromCode(instrumentId: string): string {
    if (!instrumentId) return ''

    // 提取字母部分作为品种代码，如 rb2509 -> rb
    const match = instrumentId.match(/^([a-zA-Z]+)/)
    return match ? match[1].toUpperCase() : ''
  }

  /**
   * 订阅单个合约的行情数据（支持多面板共享）
   */
  public async subscribeContractMarketData(contractCode: string, panelId?: string): Promise<boolean> {
    try {
      // 检查行情 API 是否已连接
      const mdSessionId = ctpService.getMdSessionId()
      if (!mdSessionId) {
        return false
      }

      const subscriptionManager = SubscriptionManager.getInstance()
      const actualPanelId = panelId || `panel_${Date.now()}`

      // 检查是否是第一个订阅者
      const isFirstSubscriber = subscriptionManager.addSubscription(contractCode, actualPanelId)

      if (isFirstSubscriber) {
        // 只有第一个订阅者才真正向CTP发起订阅

        const result = await ctpService.subscribeMarketData([contractCode])

        if (result.success) {
          return true
        } else {
          // 订阅失败，移除记录
          subscriptionManager.removeSubscription(contractCode, actualPanelId)
          return false
        }
      } else {
        // 不是第一个订阅者，直接返回成功（复用现有订阅）
        return true
      }
    } catch (error) {
      return false
    }
  }

  /**
   * 取消订阅单个合约的行情数据（支持多面板共享）
   */
  public async unsubscribeContractMarketData(contractCode: string, panelId?: string): Promise<boolean> {
    try {
      // 检查行情 API 是否已连接
      const mdSessionId = ctpService.getMdSessionId()
      if (!mdSessionId) {
        return false
      }

      const subscriptionManager = SubscriptionManager.getInstance()
      const actualPanelId = panelId || `panel_${Date.now()}`

      // 检查是否是最后一个订阅者
      const isLastSubscriber = subscriptionManager.removeSubscription(contractCode, actualPanelId)

      if (isLastSubscriber) {
        // 只有最后一个订阅者才真正向CTP发起取消订阅
        const result = await ctpService.unsubscribeMarketData([contractCode])
        if (result.success) {
          return true
        } else {
          return false
        }
      } else {
        // 不是最后一个订阅者，直接返回成功（保持现有订阅）
        return true
      }
    } catch (error) {
      return false
    }
  }

  /**
   * 检查是否已初始化
   */
  public isDataInitialized(): boolean {
    return this.isInitialized
  }

  /**
   * 带超时机制的初始化方法
   */
  private async initializeWithTimeout(): Promise<void> {
    if (this.isLoading) {
      // 如果正在加载，等待加载完成
      while (this.isLoading) {
        await new Promise(resolve => setTimeout(resolve, 100))
      }
      return
    }

    try {
      this.isLoading = true

      // 先检查是否有缓存数据
      const hasCacheData = await this.checkCacheExists()

      if (hasCacheData) {
        console.log('📦 [ContractService] 检测到缓存文件存在，尝试从CTP查询合约数据')
        
        // 有缓存时，尝试查询CTP，如果超时则使用缓存
        try {
          const result = await this.queryFromCTP()

          // 检查是否是超时错误
          if (!result.success && result.error === 'QUERY_TIMEOUT') {
            console.log('⏰ [ContractService] CTP查询超时，使用缓存数据')
            const success = await this.loadFromCache()
            if (success) {
              this.lastDataSource = 'cache'
              this.isInitialized = true
              console.log(`✅ [ContractService] 从缓存加载成功，共 ${this.contracts.length} 个合约`)
              return
            } else {
              throw new Error('缓存数据加载失败')
            }
          }

          if (result.success && result.data) {
            console.log(`✅ [ContractService] CTP查询成功，共 ${result.data.length} 个合约`)
            this.processRealContractData(result.data)
            await this.saveToCache()
            this.lastDataSource = 'ctp'
            this.isInitialized = true
            return
          } else {
            throw new Error(result.error || '查询合约信息失败')
          }
        } catch (error) {
          console.error('❌ [ContractService] CTP查询异常:', error)
          throw error
        }
      } else {
        console.log('📭 [ContractService] 缓存文件不存在，必须从CTP查询合约数据')
        
        // 没有缓存数据，必须查询 CTP API，持续轮询直到成功
        let retryCount = 0
        const maxRetries = 999 // 设置一个很大的值，实际上会一直重试
        
        while (retryCount < maxRetries) {
          const result = await this.queryFromCTP()

          // 如果查询成功，保存缓存并返回
          if (result.success && result.data) {
            console.log(`✅ [ContractService] CTP查询成功，共 ${result.data.length} 个合约`)
            this.processRealContractData(result.data)
            await this.saveToCache()
            this.lastDataSource = 'ctp'
            this.isInitialized = true
            return
          }

          // 如果是超时错误，继续重试
          if (!result.success && result.error === 'QUERY_TIMEOUT') {
            retryCount++
            console.log(`⏰ [ContractService] CTP查询超时且无缓存，第 ${retryCount} 次重试...`)
            // 等待2秒后重试
            await new Promise(resolve => setTimeout(resolve, 2000))
            continue
          }

          // 如果是其他错误，也继续重试（因为没有缓存，必须获取数据）
          retryCount++
          console.log(`❌ [ContractService] CTP查询失败: ${result.error}，第 ${retryCount} 次重试...`)
          // 等待2秒后重试
          await new Promise(resolve => setTimeout(resolve, 2000))
        }

        // 理论上不会到这里，除非达到最大重试次数
        throw new Error('查询合约信息失败：已达到最大重试次数')
      }
    } catch (error) {
      console.error('❌ [ContractService] 初始化失败:', error)
      throw error
    } finally {
      this.isLoading = false
    }
  }

  /**
   * 检查缓存是否存在
   */
  private async checkCacheExists(): Promise<boolean> {
    try {
      const cacheData = await ContractCache.loadContractData()
      return cacheData !== null && cacheData.contracts.length > 0
    } catch (error) {
      return false
    }
  }

  /**
   * 从 CTP API 查询合约数据
   */
  private async queryFromCTP(): Promise<any> {
    return await ctpService.queryInstruments()
  }

  /**
   * 创建超时 Promise
   */
  private createTimeoutPromise(ms: number): Promise<never> {
    return new Promise((_, reject) => {
      setTimeout(() => reject(new Error('TIMEOUT')), ms)
    })
  }

  /**
   * 强制重新初始化
   */
  public async forceReinitialize(): Promise<void> {
    this.isInitialized = false
    this.contracts = []
    this.categories = []
    await this.initialize()
  }

  /**
   * 保存合约数据到缓存
   */
  private async saveToCache(): Promise<void> {
    try {
      await ContractCache.saveContractData(this.contracts, this.categories)
    } catch (error) {
      // 缓存保存失败不影响主流程
    }
  }

  /**
   * 从缓存加载合约数据
   */
  private async loadFromCache(): Promise<boolean> {
    try {
      const cacheData = await ContractCache.loadContractData()

      if (cacheData) {
        this.contracts = cacheData.contracts
        this.categories = cacheData.categories
        return true
      }

      return false
    } catch (error) {
      return false
    }
  }

  /**
   * 清除本地缓存
   */
  public async clearCache(): Promise<boolean> {
    return await ContractCache.clearCache()
  }

  /**
   * 获取缓存信息
   */
  public async getCacheInfo() {
    return await ContractCache.getCacheInfo()
  }

  /**
   * 获取最后一次数据来源
   */
  public getLastDataSource(): 'ctp' | 'cache' | 'unknown' {
    return this.lastDataSource
  }
}

// 导出单例实例
export const contractService = ContractService.getInstance()
